﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using BattleCity.GameLogic;

namespace BattleCity.Rendering
{
    public class GridRenderer
    {
        private VertexBuffer tileVertexBuffer;
        private IndexBuffer tileIndexBuffer;
        private GraphicsDevice graphicsDevice;

        public VertexBuffer VertexBuffer { get { return tileVertexBuffer; } }
        public IndexBuffer IndexBuffer   { get { return tileIndexBuffer; } }
        public int PrimitiveCount { get { return tileVertexBuffer.VertexCount / 2; } }

        public GridRenderer(GraphicsDevice graphicsDevice)
        {
            this.graphicsDevice = graphicsDevice;

            //calcolo di quante tile è composta la griglia
            int tileCount = 0;
            for (int i = 0; i < 13; ++i)
            {
                for (int j = 0; j < 13; ++j)
                {
                    if (!GameState.gameState.BlockGrid[i, j].makeUp.IsSpace) tileCount++;
                }
            }

            //creo i buffers (index e vertex) con le tile della griglia
            VertexPositionNormalTexture[] vertexData = new VertexPositionNormalTexture[tileCount * 16];
            short[] indexData = new short[tileCount * 24];

            tileVertexBuffer = new VertexBuffer(graphicsDevice, VertexPositionNormalTexture.VertexDeclaration, 16 * tileCount, BufferUsage.None);
            tileIndexBuffer = new IndexBuffer(graphicsDevice, IndexElementSize.SixteenBits, 24 * tileCount, BufferUsage.None);

            int vertexOffset = 0;
            int indexOffset = 0;
            for (int i = 0; i < 13; ++i)
            {
                for (int j = 0; j < 13; ++j)
                {
                    if (!GameState.gameState.BlockGrid[i, j].makeUp.IsSpace)
                    {
                        Vector3 pos = GameState.gameState.BlockGrid[i, j].position.xnaVector3YView;
                        float x = pos.X;
                        float z = pos.Z;

                        //front face
                        vertexData[vertexOffset + 0] = new VertexPositionNormalTexture(new Vector3(x - 2f, -1.0f, z + 2f), Vector3.UnitZ, new Vector2(0, 0.49f));
                        vertexData[vertexOffset + 1] = new VertexPositionNormalTexture(new Vector3(x - 2f, 0.0f, z + 2f), Vector3.UnitZ, new Vector2(0, 0));
                        vertexData[vertexOffset + 2] = new VertexPositionNormalTexture(new Vector3(x + 2f, 0.0f, z + 2f), Vector3.UnitZ, new Vector2(0.49f, 0));
                        vertexData[vertexOffset + 3] = new VertexPositionNormalTexture(new Vector3(x + 2f, -1.0f, z + 2f), Vector3.UnitZ, new Vector2(0.49f, 0.49f));

                        indexData[indexOffset + 0] = (short)(vertexOffset + 0);
                        indexData[indexOffset + 1] = (short)(vertexOffset + 1);
                        indexData[indexOffset + 2] = (short)(vertexOffset + 2);
                        indexData[indexOffset + 3] = (short)(vertexOffset + 2);
                        indexData[indexOffset + 4] = (short)(vertexOffset + 3);
                        indexData[indexOffset + 5] = (short)(vertexOffset + 0);

                        //right face
                        vertexData[vertexOffset + 4] = new VertexPositionNormalTexture(new Vector3(x + 2f, -1.0f, z + 2f), Vector3.UnitX, new Vector2(0, 0.49f));
                        vertexData[vertexOffset + 5] = new VertexPositionNormalTexture(new Vector3(x + 2f, 0.0f, z + 2f), Vector3.UnitX, new Vector2(0, 0));
                        vertexData[vertexOffset + 6] = new VertexPositionNormalTexture(new Vector3(x + 2f, 0.0f, z - 2f), Vector3.UnitX, new Vector2(0.49f, 0));
                        vertexData[vertexOffset + 7] = new VertexPositionNormalTexture(new Vector3(x + 2f, -1.0f, z - 2f), Vector3.UnitX, new Vector2(0.49f, 0.49f));

                        indexData[indexOffset + 6] = (short)(vertexOffset + 4);
                        indexData[indexOffset + 7] = (short)(vertexOffset + 5);
                        indexData[indexOffset + 8] = (short)(vertexOffset + 6);
                        indexData[indexOffset + 9] = (short)(vertexOffset + 6);
                        indexData[indexOffset + 10] = (short)(vertexOffset + 7);
                        indexData[indexOffset + 11] = (short)(vertexOffset + 4);

                        //left face
                        vertexData[vertexOffset + 8] = new VertexPositionNormalTexture(new Vector3(x - 2f, -1.0f, z + 2f), Vector3.UnitX, new Vector2(0, 0.49f));
                        vertexData[vertexOffset + 9] = new VertexPositionNormalTexture(new Vector3(x - 2f, 0.0f, z + 2f), Vector3.UnitX, new Vector2(0, 0));
                        vertexData[vertexOffset + 10] = new VertexPositionNormalTexture(new Vector3(x - 2f, 0.0f, z - 2f), Vector3.UnitX, new Vector2(0.49f, 0));
                        vertexData[vertexOffset + 11] = new VertexPositionNormalTexture(new Vector3(x - 2f, -1.0f, z - 2f), Vector3.UnitX, new Vector2(0.49f, 0.5f));

                        indexData[indexOffset + 12] = (short)(vertexOffset + 8);
                        indexData[indexOffset + 13] = (short)(vertexOffset + 11);
                        indexData[indexOffset + 14] = (short)(vertexOffset + 10);
                        indexData[indexOffset + 15] = (short)(vertexOffset + 10);
                        indexData[indexOffset + 16] = (short)(vertexOffset + 9);
                        indexData[indexOffset + 17] = (short)(vertexOffset + 8);

                        //up face
                        if (GameState.gameState.BlockGrid[i, j].makeUp.IsStealth)
                        {
                            vertexData[vertexOffset + 12] = new VertexPositionNormalTexture(new Vector3(x - 2f, 0.0f, z + 2f), Vector3.UnitY, new Vector2(0.5f, 0.49f));
                            vertexData[vertexOffset + 13] = new VertexPositionNormalTexture(new Vector3(x - 2f, 0.0f, z - 2f), Vector3.UnitY, new Vector2(0.5f, 0));
                            vertexData[vertexOffset + 14] = new VertexPositionNormalTexture(new Vector3(x + 2f, 0.0f, z - 2f), Vector3.UnitY, new Vector2(1.0f, 0));
                            vertexData[vertexOffset + 15] = new VertexPositionNormalTexture(new Vector3(x + 2f, 0.0f, z + 2f), Vector3.UnitY, new Vector2(1.0f, 0.49f));
                        }
                        else
                        {
                            vertexData[vertexOffset + 12] = new VertexPositionNormalTexture(new Vector3(x - 2f, 0.0f, z + 2f), Vector3.UnitY, new Vector2(0, 0.49f));
                            vertexData[vertexOffset + 13] = new VertexPositionNormalTexture(new Vector3(x - 2f, 0.0f, z - 2f), Vector3.UnitY, new Vector2(0, 0));
                            vertexData[vertexOffset + 14] = new VertexPositionNormalTexture(new Vector3(x + 2f, 0.0f, z - 2f), Vector3.UnitY, new Vector2(0.49f, 0));
                            vertexData[vertexOffset + 15] = new VertexPositionNormalTexture(new Vector3(x + 2f, 0.0f, z + 2f), Vector3.UnitY, new Vector2(0.49f, 0.49f));
                        }

                        indexData[indexOffset + 18] = (short)(vertexOffset + 12);
                        indexData[indexOffset + 19] = (short)(vertexOffset + 13);
                        indexData[indexOffset + 20] = (short)(vertexOffset + 14);
                        indexData[indexOffset + 21] = (short)(vertexOffset + 14);
                        indexData[indexOffset + 22] = (short)(vertexOffset + 15);
                        indexData[indexOffset + 23] = (short)(vertexOffset + 12);

                        vertexOffset += 16;
                        indexOffset += 24;
                    }
                }
            }

            tileVertexBuffer.SetData<VertexPositionNormalTexture>(vertexData);
            tileIndexBuffer.SetData<short>(indexData);
        }

        public void Draw()
        {
            graphicsDevice.Indices = IndexBuffer;
            graphicsDevice.SetVertexBuffer(VertexBuffer);
            graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, VertexBuffer.VertexCount, 0, PrimitiveCount);
        }
    }
}
